/** 
 * SingleInningParser.java Created by iweerarathna on Aug 29, 2011.
 * 
 * Copyright (c) 2011 Virtusa Corporation. All Rights Reserved.<br><br>. 
 * 
 */
package org.uim.cricket.analyzer.parsers.aggr.impl;

import java.util.HashMap;
import java.util.List;

import org.uim.cricket.analyzer.parsers.Plogger;
import org.uim.cricket.analyzer.parsers.aggr.*;
import org.uim.cricket.analyzer.parsers.batting.AbstractBattingInningsParser;
import org.uim.cricket.analyzer.parsers.batting.DidNotBatParsable;
import org.uim.cricket.analyzer.parsers.bowling.AbstractBowlingInningsParser;
import org.uim.cricket.analyzer.parsers.inning.*;
import org.uim.cricket.analyzer.parsers.partnerships.AbstractFallOfWicketsParser;
import org.uim.cricket.entities.Player;
import org.uim.cricket.entities.aggr.SingleInning;
import org.uim.cricket.entities.batting.BatsmanOutDetails;
import org.uim.cricket.entities.batting.BattingInning;
import org.uim.cricket.entities.batting.OutTypes;
import org.uim.cricket.util.HTMLStringUtils;
import org.uim.cricket.util.MyStringUtils;

/**
 * TODO Class description goes here.
 * @version 
 * @author iweerarathna
 */
public class SingleInningParser implements SingleInningParsable {

    private InningExtrasParsable extraParser = null;
    private InningTotalsParsable totalParser = null;
    private DidNotBatParsable dnbParser = null;
    
    private AbstractBattingInningsParser absBatsParser = null;
    private AbstractBowlingInningsParser absBowlParser = null;
    private AbstractFallOfWicketsParser absFowParser = null;
    
    public SingleInningParser() {
        
    }
    
    public SingleInningParser(InningExtrasParsable theExtraParser, InningTotalsParsable theTotalParser) {
        this.extraParser = theExtraParser;
        this.totalParser = theTotalParser;
    }
    
    @Override
    public SingleInning parseSingleInning(StringBuilder source) {
        if (source == null || source.length() == 0) return null;
        String[] tables = MyStringUtils.splitInBetween(source.toString(), "<table", "</table>");
        
        SingleInning inn = new SingleInning();

        for (int i=0;i<tables.length;i++) {
            String table = "<table" + tables[i];
            
            int pos = table.indexOf('>');
            String tag = table.substring(0, pos+1);
            HashMap<String, String> attribs = HTMLStringUtils.getHTMLAttributes(tag);
            String id = null;
            
            if ((id = attribs.get("id")) != null) {
                
                if (id.toLowerCase().startsWith("inningsbat")) {
                    
                    String[] rows = MyStringUtils.splitInBetween(table, "<tr", "</tr>");
                    StringBuilder batrows = new StringBuilder();
                    
                    for (int j=0; j<rows.length; j++) {
                        rows[j] = "<tr" + rows[j] + "</tr>";
                        String[] cols = MyStringUtils.splitInBetween(rows[j], "<td", "</td>");
                        String type = this.isInningDetailRow(cols);
                        if (type == null) {
                            batrows.append(rows[j]);
                            continue;
                        }
                        
                        if (type.equalsIgnoreCase("extras")) {
                            
                            if (this.extraParser != null) {
                                Plogger.debug("    parsing extras...");
                                inn.setExtras(this.extraParser.parseExtras("<td" + rows[j] + "</td>"));
                                Plogger.debug("    ok.");
                            } else {
                                Plogger.printHardWarn("No InningExtrasParsable interface is defined!");
                            }
                            
                            
                        } else if (type.equalsIgnoreCase("total")) {
                            
                            if (this.totalParser != null) {
                                Plogger.debug("    parsing totals...");
                                inn.setTotals(this.totalParser.parseTotals("<td" + rows[j] + "</td>"));
                                Plogger.debug("    ok.");
                            } else {
                                Plogger.printHardWarn("No InningTotalsParsable interface is defined!");
                            }
                            
                            
                        }
                        
                    }
                    
                    if (this.absBatsParser != null) {
                        Plogger.debug("    parsing all batting innings...");
                        inn.setBatInnings(this.absBatsParser.parseAllBattingInnings(batrows, inn));
                        Plogger.debug("    completed parsing all batting innings.");
                    } else {
                        Plogger.printHardWarn("No AbstractBattingInningParser class has been assigned!");
                    }
                    
                    
                } else if (id.toLowerCase().startsWith("inningsbowl")) {
                    
                    if (this.absBowlParser != null) {
                        Plogger.debug("    parsing all bowling innings...");
                        inn.setBowlInnings(this.absBowlParser.parseAllBowlingInnings(new StringBuilder(table), inn));
                        Plogger.debug("    completed parsing all bowling innings.");
                    } else {
                        Plogger.printHardWarn("No AbstractBowlingInningParser class has been assigned!");
                    }
                    
                }
                
                
                
            } else {
                
                String[] titles = MyStringUtils.splitInBetween(table, "<b>", "</b>");
                if (titles != null) {

                    if (titles[0].toLowerCase().startsWith("did")) {
                        
                        Plogger.debug("    parsing all did not bats...");
                        
                        Player[] batsmen = this.dnbParser.parseDidNotBatBatsmans(table);
                        if (batsmen != null) {
                            List<BattingInning> binns = inn.getBatInnings();
                            
                            for (int j=0;j<batsmen.length;j++) {
                                BattingInning batinn = new BattingInning();
                                batinn.setBatsman(batsmen[j]);
                                BatsmanOutDetails outd = new BatsmanOutDetails();
                                outd.setOutType(OutTypes.DID_NOT_BAT);
                                binns.add(batinn);
                            }
                            
                        }
                        
                        Plogger.debug("    completed parsing all did not bats...");
                        
                    } else if (titles[0].toLowerCase().startsWith("fall")) {
                        
                        Plogger.debug("    parsing all fall of wickets...");
                        inn.setFallWickets(this.absFowParser.parseAllFallOfWickets(table));
                        Plogger.debug("    completed parsing all fall of wickets...");
                        
                    }
                    
                }
                
            }
            
        }
        
        return inn;
    }

    private String isInningDetailRow(String[] cols) {
        for (int i=0;i<cols.length;i++) {
            cols[i] = "<td" + cols[i];
            
            if (cols[i].toLowerCase().startsWith("<td class=\"inningsdetails\">")) {
                return HTMLStringUtils.cleanHTMLTags(cols[i]);
            }
        }
        return null;
    }
    
    public void setTotalParser(InningTotalsParsable totalParser) {
        this.totalParser = totalParser;
    }
    
    public void setExtraParser(InningExtrasParsable extraParser) {
        this.extraParser = extraParser;
    }
    
    public InningTotalsParsable getTotalParser() {
        return totalParser;
    }
    
    public InningExtrasParsable getExtraParser() {
        return extraParser;
    }
    
    public void setAbsBatsParser(AbstractBattingInningsParser absBatsParser) {
        this.absBatsParser = absBatsParser;
    }
    
    public AbstractBattingInningsParser getAbsBatsParser() {
        return absBatsParser;
    }
    
    public void setAbsBowlParser(AbstractBowlingInningsParser absBowlParser) {
        this.absBowlParser = absBowlParser;
    }
    
    public AbstractBowlingInningsParser getAbsBowlParser() {
        return absBowlParser;
    }
    
    public void setAbsFowParser(AbstractFallOfWicketsParser absFowParser) {
        this.absFowParser = absFowParser;
    }
    
    public AbstractFallOfWicketsParser getAbsFowParser() {
        return absFowParser;
    }
    
    public void setDnbParser(DidNotBatParsable dnbParser) {
        this.dnbParser = dnbParser;
    }
    
    public DidNotBatParsable getDnbParser() {
        return dnbParser;
    }
    
}
